/*
 * Copyright Paul James Mutton, 2001-2007, http://www.jibble.org/
 * This file is part of PircBot.
 * This software is dual-licensed, allowing you to choose between the GNU
 * General Public License (GPL) and the www.jibble.org Commercial License.
 * Since the GPL may be too restrictive for use in a proprietary application,
 * a commercial license is also provided. Full license information can be
 * found at http://www.jibble.org/licenses/
 */
package org.jibble.pircbot;

import java.io.BufferedWriter;

import output.IRCOutput;
import output.OutputQueue;

/**
 * A Thread which is responsible for sending messages to the IRC server. Messages are obtained from the outgoing message queue and
 * sent immediately if possible. If there is a flood of messages, then to avoid getting kicked from a channel, we put a small
 * delay between each one.
 * 
 * @author Paul James Mutton, <a href="http://www.jibble.org/">http://www.jibble.org/</a>
 * @version 1.4.6 (Build time: Wed Apr 11 19:20:59 2007)
 */
public class OutputThread extends Thread {

   /**
    * A static method to write a line to a BufferedOutputStream and then pass the line to the log method of the supplied PircBot
    * instance.
    * 
    * @param bot
    *           The underlying PircBot instance.
    * @param out
    *           The BufferedOutputStream to write to.
    * @param line
    *           The line to be written. "\r\n" is appended to the end.
    * @param encoding
    *           The charset to use when encoing this string into a byte array.
    */
   protected static void sendRawLine(final PircBot bot, final BufferedWriter bwriter, final String linein) {
	  String line = linein;
	  if (line.length() > bot.getMaxLineLength() - 2) {
		 line = line.substring(0, bot.getMaxLineLength() - 2);
	  }
	  synchronized (bwriter) {
		 try {
			bwriter.write(line + "\r\n");
			bwriter.flush();
			bot.log(">>>" + line);
		 } catch (final Exception e) {
			// Silent response - just lose the line.
		 }
	  }
   }

   private final PircBot _bot;

   private final OutputQueue _outQueue;

   /**
    * Constructs an OutputThread for the underlying PircBot. All messages sent to the IRC server are sent by this OutputThread to
    * avoid hammering the server. Messages are sent immediately if possible. If there are multiple messages queued, then there is
    * a delay imposed.
    * 
    * @param bot
    *           The underlying PircBot instance.
    * @param outQueue
    *           The Queue from which we will obtain our messages.
    */
   public OutputThread(final PircBot bot, final OutputQueue outQueue, final String name) {
	  super();
	  _bot = bot;
	  _outQueue = outQueue;
	  setName(name);
   }

   /**
    * This method starts the Thread consuming from the outgoing message Queue and sending lines to the server.
    */

   @Override
   public void run() {
	  boolean running = true;
	  while (running) {
		 IRCOutput output = null;
		 synchronized (_outQueue) {
			while ((output = _outQueue.next(_bot.getNick())) == null) {
			   try {
				  _outQueue.wait();
			   } catch (InterruptedException e) {
				  // do nothing
			   }
			}
		 }
		 while (!output.getOutput().isEmpty()) {
			_bot.sendRawLine(output.getAddress() + output.getOutput().remove(0));
			try {
			   // Small delay to prevent spamming of the
			   // channel
			   Thread.sleep(PircBot.getMessageDelay());
			} catch (InterruptedException e) {
			   // do nothing
			}
		 }
		 synchronized (_outQueue) {
			_outQueue.finishedWork(output.getTarget());
		 }
	  }
   }

}
